const fs = require('fs');
const path = require('path');
const { createWorker } = require('tesseract.js');

const IMAGE_PATH = path.resolve('output/WechatIMG2.jpg');
const OUTPUT_MD = path.resolve('doc/坐骑训练表格.md');

async function ocrImage() {
    console.log('[OCR] 初始化 worker (chi_sim+eng) ...');
    console.time('[OCR] 初始化耗时');
    const worker = await createWorker('chi_sim+eng');
    console.timeEnd('[OCR] 初始化耗时');
    try {
        console.log('[OCR] 开始识别图片:', IMAGE_PATH);
        console.time('[OCR] 识别耗时');
        const { data } = await worker.recognize(IMAGE_PATH);
        console.timeEnd('[OCR] 识别耗时');
        console.log('[OCR] 识别完成，文本长度=', (data.text || '').length);
        return data.text || '';
    } finally {
        console.log('[OCR] 释放 worker ...');
        await worker.terminate();
        console.log('[OCR] worker 已释放');
    }
}

function cleanText(text) {
    console.log('[CLEAN] 原始文本长度=', text.length);
    const cleaned = text
        .replace(/[\u200b\u200c\u200d\ufeff]/g, '')
        .replace(/\t/g, ' ')
        .replace(/\r/g, '')
        .replace(/[ ]{2,}/g, ' ');
    console.log('[CLEAN] 清洗后文本长度=', cleaned.length);
    return cleaned;
}

function parseRows(text) {
    console.log('[PARSE] 开始按行解析 ...');
    const lines = text.split('\n').map(l => l.trim()).filter(Boolean);
    console.log('[PARSE] 行数=', lines.length);
    const rows = [];
    for (const line of lines) {
        const m = line.match(/^(\d{1,3})\s+(.+)$/);
        if (!m) continue;
        const lvl = parseInt(m[1], 10);
        if (isNaN(lvl)) continue;
        const nums = line.match(/\d+/g) || [];
        const rest = nums.map(n => parseInt(n, 10)).filter((_, idx) => idx > 0);
        rows.push({ lvl, raw: line, nums: rest });
    }
    console.log('[PARSE] 解析到数据行数=', rows.length);
    return rows;
}

function formatMarkdown(rows) {
    const header = ['等级', '训练次数(本级)', '屏幕次数', '当前次数', '升级总次数', '升段个数', '当前个数'];
    const lines = [];
    lines.push(`# 坐骑训练表格`);
    lines.push('来源: output/WechatIMG2.jpg OCR 解析');
    lines.push('');
    lines.push(`| ${header.join(' | ')} |`);
    lines.push(`| ${header.map(() => '---').join(' | ')} |`);
    for (const r of rows) {
        const cols = [r.lvl, ...(r.nums.slice(0, 6))];
        while (cols.length < 7) cols.push('');
        lines.push(`| ${cols.join(' | ')} |`);
    }
    return lines.join('\n');
}

function sampleCheck(rows, n = 20) {
    console.log('[CHECK] 开始抽样校验, 目标样本数=', n);
    const samples = [];
    const step = Math.max(1, Math.floor(rows.length / n));
    for (let i = 0; i < rows.length && samples.length < n; i += step) {
        const r = rows[i];
        const ok = r && Array.isArray(r.nums) && r.nums.length >= 3 && r.nums.every(x => x >= 0);
        samples.push({ lvl: r.lvl, ok });
    }
    const allOk = samples.every(s => s.ok);
    console.log('[CHECK] 样本校验结果(allOk)=', allOk);
    return { samples, allOk };
}

async function main() {
    console.log('[MAIN] 图片路径=', IMAGE_PATH);
    if (!fs.existsSync(IMAGE_PATH)) {
        console.error('图片不存在:', IMAGE_PATH);
        process.exit(1);
    }
    const text = await ocrImage();
    const cleaned = cleanText(text);
    const rows = parseRows(cleaned);
    if (rows.length === 0) {
        console.error('OCR 结果为空或无法解析为行');
        process.exit(1);
    }
    const { samples, allOk } = sampleCheck(rows, 20);
    const md = formatMarkdown(rows);
    fs.writeFileSync(OUTPUT_MD, md, 'utf8');
    console.log('[WRITE] 已写入 Markdown:', OUTPUT_MD);
    console.log('[SAMPLES]', samples);
    if (!allOk) {
        console.warn('注意: 抽样存在格式风险，请人工复核。');
    }
    console.log('[DONE] 解析完成');
}

main().catch(e => { console.error(e); process.exit(1); });
